WebAssembly Migration Guide

(P)NaCl Deprecation Announcements

Given the momentum of cross-browser WebAssembly support, we plan to focus our native code efforts on WebAssembly going forward and plan to remove support for PNaCl in Q4 2019 (except for Chrome Apps). We believe that the vibrant ecosystem around WebAssembly makes it a better fit for new and existing high-performance web apps and that usage of PNaCl is sufficiently low to warrant deprecation.

As of Chrome 76, PNaCl on the open web has been moved behind an Origin Trial, which is a mechanism for web developers to register and get access to a feature that isn’t on by default. This is usually a new proposed feature but in this case it’s a feature being deprecated. A developer can register on the Origin Trial Console and receive a token, which can be embedded into a page and will enable the feature without the user needing to use a flag. (For more details see the linked guide). The trial is scheduled to last through Chrome 78, approximately until December 2019. This change is not intended to affect NaCl or PNaCl in Chrome Apps or extensions, and the “enable-nacl” flag in chrome://flags can also be used to enable PNaCl locally for testing (this flag also retains its current function of enabling non-PNaCl “native” NaCl on any page).

We also recently announced the deprecation Q1 2018 of Chrome Apps outside of Chrome OS.

Toolchain Migration

For the majority of (P)NaCl uses cases we recommend transitioning from the NaCl SDK to Emscripten. Migration is likely to be reasonably straightforward if your application is portable to Linux, uses SDL, or POSIX APIs. While direct support for NaCl / Pepper APIs in not available, we’ve attempted to list Web API equivalents. For more challenging porting cases, please reach out on native-client-discuss@googlegroups.com

API Migration

We’ve outlined here the status of Web Platform substitutes for each of the APIs exposed to (P)NaCl. Additionally, the table lists the library or option in Emscripten that offers the closest substitute.

We expect to add shared memory threads support to WebAssembly in 2017, as threads are crucial to matching (P)NaCl’s most interesting use cases. Migration items which assume forthcoming threads support are marked below. If your application’s flow control relies heavily on blocking APIs, you may also find threads support is required for convenient porting.

While we’ve tried to be accurate in this table, there are no doubt errors or omissions. If you encounter one, please reach out to us on native-client-discuss@googlegroups.com

PPAPI

PPB_Audio

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x SDL (partial) GAP (partial) - AudioWorkletNode ROUGHLY equivalent The AudioWorkletSpec is done, but AudioDeviceClient may be a better fit for this API. The AudioDeviceClient is still being specified by the community. The worklet may not be the rough equivalent for this API.
GetCurrentConfig SDL AudioContext.* (gets back settings passed in)
StartPlayback SDL AudioBufferSourceNode.start
StopPlayback SDL AudioBufferSourceNode.stop

PPB_AudioBuffer

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetTimestamp SDL AudioBufferSourceNode.start (parameter) Passed in each time instead of attached to the buffer.
SetTimestamp SDL AudioBufferSourceNode.start (parameter)
GetSampleRate SDL AudioBuffer.sampleRate
GetSampleSize GAP GAP - WebAudio only uses 32-bit float, PPAPI does 16-bit int. PPAPI theoretically supports multiple sampling sizes. In practice, it only supports 16-bit samples. Unfortunately, developers have requested 16-bit sample sizes to save on memory use. The next version of the Web Audio spec will implement support for 16-bit samples. An optimization for AudioBuffer could be implemented similar to Firefox by using 16-bit buffer for audio that comes from decodeAudioData
GetNumberOfChannels SDL AudioBuffer.numberOfChannels
GetDataBuffer SDL AudioBuffer.getChannelData
GetBufferSize SDL AudioBuffer.length

PPB_AudioConfig

PPAPI Method Assumes Threads Emscripten Web API Limitations
CreateStereo16Bit GAP GAP - Only 32-bit float samples supported The next version of the Web Audio spec will implement support for 16-bit samples.
GetSampleRate SDL AudioContext.sampleRate
GetSampleFrameCount SDL AudioBuffer.length
RecommendSampleRate SDL AudioContext.sampleRate (from default construct) An AudioContext will have the preferred sampling rate that matchs the actual sample rate of the hardware audio device by default.
RecommendSampleFrameCount GAP GAP - Would be handled with the planned AudioDeviceClient There is an open issue to allow a user-specified size, but that is still being defined. This is probably best handled with AudioDeviceClient which can tell you what the appropriate size would be for the given hardware.

PPB_Console

PPAPI Method Assumes Threads Emscripten Web API Limitations
Log utime console.log/warn/error/...
LogWithSource GAP GAP The Console API is regarded as a sufficiently complete replacement, unless there are specific use cases raised by developers for the functionality provided by LogWithSource. DevTools Source Maps can be used to debug transpiled JavaScript in their original source language.

PPB_Core

PPAPI Method Assumes Threads Emscripten Web API Limitations
getTime utime new Date().getTime()
getTimeTicks utime new Date().getTime()
IsMainThread GAP window.document !== undefined
CallOnMainThread GAP Worker.postMessage + Atomics.wait Equivalent synchronization can be built.

PPB_FileIO

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) window.chooseFileSystemEntries() Create and open are used differently, but the pieces are of equal power.
Open FS (partial) window.chooseFileSystemEntries()
Query FS (partial) Blob.size, FileSystemHandle.getFile(), FileSystemHandle.getDirectory(), File.lastModified GAP (partial) - Blob.type can also be used to check the MIME type. The file system type, creation time, and last access time can not be determined with the Native File System API.
Touch FS (partial) FileSystemDirectoryHandle.getFile("name", {create: true})
Read FS (partial) Blob.slice().arrayBuffer()
Write FS (partial) FileSystemWriter.write()
SetLength FS (partial) FileSystemWriter.truncate()
Flush GAP (partial) GAP (partial) - Files are flushed when FileSystemWrite.close() is called This is intended by design because the Native File System API files are exposed to the OS, therefore a Safe Browsing check needs to be performed before data is shown to the OS.
Close FS (partial) FileSystemWriter.close() Does not cancel pending operations, but flushes any data written so far to disk.
ReadToArray GAP Blob.slice().arrayBuffer() or Blob.arrayBuffer() Allows multiple subrange reads in parallel.

PPB_FileRef

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) FileSystemDirectoryHandle.getFile("name", {create: true})
GetFileSystemType FS (partial) FileSystem.type
GetName FS (partial) File.name
GetPath FS (partial) GAP (partial) - With the Native File System API, the relative path of a file can be determined from reference to a directory that contains the file using FileSystemHandle.resolve(FileSystemHandle) The absolute path of a file cannot be determined, and the user has to grant permission to access the directory containing the file.
GetParent FS (partial) GAP (partial) - With the Native File System API, the relative path of a file can be determined from reference to a directory that contains the file using FileSystemHandle.resolve(FileSystemHandle) The user has to grant permission to access the directory containing the file.
MakeDirectory FS (partial) FileSystemHandle.getDirectory(..., {createIfNotExists: true})
Touch FS (partial) FileSystemDirectoryHandle.getFile("name", {create: true}) Modify time can be bumped by writing.
Delete FS (partial) FileSystemDirectoryHandle.removeEntry() Unlike the PPAPI, directories do not have to be empty.
Rename FS (partial) GAP (partial) - With the Native File System API, the file can be written with the new name using a combination of FileSystemFileHandle.getFile() for the new name and FileSystemFileHandle.createWriter().write() with the contents of the old file. Then FileSystemDirectoryHandle.removeEntry() to delete the old file. There is not a direct API that will do this in one step in the Native File System API.
Query GAP (partial) Blob.size, FileSystemHandle.getFile(), FileSystemHandle.getDirectory(), File.lastModified GAP (partial) - Blob.type can also be used to check the MIME type. The file system type, creation time, and last access time can not be determined with the Native File System API.
ReadDirectoryEntries FS (partial) FileSystemDirectoryHandle.getEntries()

PPB_FileSystem

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) window.requestFileSystem JS API does both in one step
Open GAP window.requestFileSystem JS API does both in one step
GetType GAP FileSystem.type

PPB_Fullscreen

PPAPI Method Assumes Threads Emscripten Web API Limitations
IsFullScreen html5.h Document.fullscreenEnabled
SetFullscreen html5.h Document.requestFullscreen
GetScreenSize html5.h Document.exitFullscreen

PPB_Gamepad

PPAPI Method Assumes Threads Emscripten Web API Limitations
Sample SDL Gamepad.* The Gamepad object exposes a timestamp relative to navigationStart. It is updated when data is received from the hardware https://www.w3.org/TR/gamepad/#gamepad-interface

PPB_Graphics2D

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL Canvas.getContext('2d')
Describe SDL Canvas.clientWidth + Canvas.clientHeight
PaintImageData SDL CanvasRenderingContext2D.putImageData
Scroll GAP CanvasRenderingContext2D.scrollIntoView, CanvasRenderingContext2D.drawImage GAP (partial) - Can be implemented by drawing the canvas onto itself, with an offset, using drawImage, and then filling in the rest.
ReplaceContents SDL CanvasRenderingContext2D.drawImage
Flush GAP No direct equivalent GAP (partial) - There is always an implicit flush at the end of draw code; this is unlikely to change. However, the combination of OffscreenCanvas and ImageBitmapRenderingContext provide similar functionality.
SetScale SDL CanvasRenderingContext2D.scale
GetScale SDL CanvasRenderingContext2D.currentTransform
SetLayerTransform SDL CanvasRenderingContext2D.setTransform CanvasRenderingContext2D.scale CanvasRenderingContext2D.translate

PPB_Graphics3D

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetAttribMaxValue OpenGL ES 3.0 WebGL 2.0 GAP (partial) - WebGL 2.0 and Emscripten's exposure of OpenGL ES 3.0 support user-defined multisampled framebuffers, in which all of the parameters configurable via PPAPI can be set.
Create SDL Canvas.getContext
GetAttribs SDL WebGLRenderingContext.getContextAttributes
SetAttribs SDL Canvas.getContext(.., OPTIONS)
GetError SDL WebGLRenderingContext.getError
ResizeBuffers SDL Canvas.width = w; Canvas.height = h;
SwapBuffers GAP No direct equivalent GAP (partial) - There is always an implicit flush at the end of draw code; this is unlikely to change. However, the combination of OffscreenCanvas and ImageBitmapRenderingContext provide similar functionality.

PPB_ImageData

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetNativeImageDataFormat SDL ImageData mandates RGBA order
IsImageDataFormatSupported SDL ImageData mandates RGBA order
Create SDL CanvasRenderingContext2d.createImageData
Describe SDL ImageData never has a stride
Map SDL ImageData.data
Unmap SDL ImageData.data

PPB_InputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
RequestInputEvents SDL No direct equivalent The lack of this feature is probably less relevant as JS / Wasm runs on the main thread and can more cheaply filter events without incurring a cross process round-trip.
RequestFilteringInputEvents SDL mouse* key* wheel* touch* composition* Events
SDL Element.addEventListener
ClearInputEventRequest SDL Element.removeEventListener
GetType SDL Event class descendants
GetTimeStamp SDL Event.timeStamp
GetModifiers SDL *Event.altKey/shiftKey/metaKey/ctrlKey

PPB_MouseInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL MouseEvent
GetButton SDL MouseEvent.button
GetPosition SDL MouseEvent.client*/page*/offset*
GetClickCount SDL dblclick' vs 'mousedown' Events
GetMovement SDL MouseEvent.movement*

PPB_WheelInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL WheelEvent
GetDelta SDL WheelEvent.delta*
GetTicks GAP GAP - deltaMode kind of contains this info, but incompletely. There is discussion on implementing a WheelEvent.deltaMode API: https://github.com/w3c/uievents/issues/181#issuecomment-537811017
GetScrollByPage GAP GAP - deltaMode kind of contains this info, but incompletely. There is discussion on implementing a WheelEvent.deltaMode API: https://github.com/w3c/uievents/issues/181#issuecomment-537811017

PPB_KeyboardInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL KeyboardEvent
GetKeyCode SDL KeyboardEvent.keyCode
GetCharacterText SDL KeyboardEvent.key
GetCode SDL KeyboardEvent.code

PPB_TouchInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL TouchEvent
AddTouchPoint SDL TouchEvent.touches.push
GetTouchCount SDL TouchEvent.touches.length
GetTouchByIndex SDL TouchEvent.touches[i]
GetTouchById SDL Touch.indentifer (to figure this out yourself)

PPB_IMEInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP CompositionEvent
GetText GAP CompositionEvent.data
GetSegmentNumber GAP GAP - No direct equivalent This data can potentially be retrieved from CompositionEvent.data.
GetSegmentOffset GAP GAP - No direct equivalent
GetTargetSegment GAP GAP - No direct equivalent
GetSelection GAP GAP - No direct equivalent

PPB_Instance

PPAPI Method Assumes Threads Emscripten Web API Limitations
BindGraphics SDL Canvas.getContext (moot as binding is automatic).
IsFullFrame GAP GAP - No equivalent to mime type handlers. NaCl apps can be registered to handle a particular mime type and own the whole document.
DidCreate N/A <Element>[key] General DOM access lets you fish out tag attributes
DidDestroy N/A N/A Not triggered for NaCl
DidChangeView N/A Element 'resize' Event
DidChangeFocus N/A Element 'focus', 'focusin', 'focusout' Events
HandleDocumentLoad N/A GAP - No way to register as a mime type handler NaCl modules via apps + a manifest entry can be set up to handle particular mime types.

PPB_MediaStreamAudioTrack

PPAPI Method Assumes Threads Emscripten Web API Limitations
Configure GAP getUserMedia() The constraints from getUserMedia() can provide the configuration values to use in MediaStreamTrack.
GetAttrib GAP MediaStreamTrack.getSettings()
GetId GAP MediaStreamTrack.id
HasEnded GAP MediaStreamTrack.readyState
GetBuffer GAP GAP - No equivalent
RecycleBuffer GAP GAP - No equivalent
Close GAP MediaStreamTrack.stop()

PPB_MediaStreamVideoTrack

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP Canvas Capture Canvas Capture provides the ability to introduce video frames programatically.
Configure GAP applyConstraints(), getUserMedia() GAP (partial) - The extent of configurations available in the Web API may differ from the PPAPI.
GetAttrib GAP MediaStreamSettings.width
GAP MediaStreamSettings.height
GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES MediaStream cannot be preloaded, so it will never buffer: https://www.w3.org/TR/mediacapture-streams/#mediastreams-in-media-elements
GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT
GetId GAP MediaStreamTrack.id
HasEnded GAP MediaStreamTrack.readyState
GetFrame GAP GAP - No equivalent
RecycleFrame GAP GAP - No equivalent
Close GAP MediaStreamTrack.stop()
GetEmptyFrame GAP GAP - No equivalent
PutFrame GAP GAP - No equivalent

PPB_MessageLoop

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create N/A Mostly moot, workers get an implicit event loop.
GetForMainThread N/A Mostly moot, workers get an implicit event loop.
GetCurrent N/A Mostly moot, workers get an implicit event loop.
AttachToCurrentThread N/A Mostly moot, workers get an implicit event loop.
Run N/A Mostly moot, workers get an implicit event loop.
PostWork N/A Mostly moot, workers get an implicit event loop.
PostQuit N/A Mostly moot, workers get an implicit event loop.

PPB_Messaging

PPAPI Method Assumes Threads Emscripten Web API Limitations
PostMessage N/A Window.postMessage
RegisterMessageHandler N/A Window.addEventListener
UnregisterMessageHandler N/A Window.removeEventListener

PPB_MouseCursor

PPAPI Method Assumes Threads Emscripten Web API Limitations
SetCursor SDL Element.style.cursor Same set of stock cursors are supported. Custom cursors can be done with url(..). Dynamic custom cursors can be done with data URIs. CSS3 supports specifying the hotspot.

PPB_MouseLock

PPAPI Method Assumes Threads Emscripten Web API Limitations
LockMouse SDL Element.requestPointerLock
UnlockMouse SDL Element.exitPointerLock

PPB_OpenGLES2

PPAPI Method Assumes Threads Emscripten Web API Limitations
Several Methods OpenGLES Close to WebGL 1.0 in functionality.
x OffscreenCanvas

PPB_TextInputController

PPAPI Method Assumes Threads Emscripten Web API Limitations
SetTextInputType GAP GAP - Potentially filled by Input Method Editor API Some developers would like to either be able to hint in this fashion, or preferrably the ability to intercept and display IME events / output inline inside a canvas.
UpdateCaretPosition GAP GAP - Potentially filled by Input Method Editor API https://www.w3.org/TR/ime-api/
CancelCompositionText GAP GAP - Potentially filled by Input Method Editor API https://www.w3.org/TR/ime-api/
UpdateSurroundingText GAP GAP - Potentially filled by Input Method Editor API https://www.w3.org/TR/ime-api/

PPB_URLLoader

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind new XMLHttpRequest();
Open embind XMLHttpRequest.open
FollowRedirect embind Request.redirect
GAP GAP - No XMLHTTPRequest equivalent
GetUploadProgress embind XMLHttpRequest 'progress' Event
GAP FetchObserver Not specced or implemented yet; https://github.com/whatwg/fetch/issues/607
GetDownloadProgress embind XMLHttpRequest 'progress' Event
GAP FetchObserver Not specced or implemented yet; https://github.com/whatwg/fetch/issues/607
GetResponseInfo embind XMLHttpRequest.getAllResponseHeaders
embind Fetch Response.*
ReadResponseBody embind XMLHttpRequest.response
embind Body.* (Response is a Body)
FinishStreamingToFile embind GAP - No direct equivalent XMLHttpRequest and Fetch both assume streaming to memory, rather than directly to a storage.
Close embind XMLHttpRequest.abort
GAP Fetch API: AbortSignal and AbortController

PPB_URLRequestInfo

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind XMLHttpRequest
embind Fetch Request
SetProperty GAP GAP - No direct equivalent for XMLHttpRequest XMLHttpRequest doesn't provide direct ways to per-request limit following redirects, stream to a file, set referrer or credentials policy.
embind Request.*
AppendDataToBody embind XMLHttpRequest.send GAP - Both must have the whole body, rather than a chunk.
embind fetch(.., options:body)
AppendFileToBody GAP fetch() upload streaming https://www.chromestatus.com/features/5274139738767360
N/A <form> You can also read with FileReader and upload, but that's more like AppendDataToBody

PPB_URLResponseInfo

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetProperty embind XMLHttpRequest.getAllResponseHeaders + others
embind Fetch Response.*
GetBodyAsFileRef embind Fetch Response (Body) .blob() Assumes storage layer optimizes transfer.

PPB_Var

PPAPI Method Assumes Threads Emscripten Web API Limitations
VarFromUtf8 embind TextDecoder.decode
VarToUtf8 embind TextEncoder.encode
VarFromResource N/A N/A
VarToResource N/A N/A

PPB_VarArray

PPAPI Method Assumes Threads Emscripten Web API Limitations
Get embind Array[i]
Set embind Array[i] = x
GetLength embind Array.length
SetLength embind Array.length = n

PPB_VarArrayBuffer

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind new ArrayBuffer(n)
ByteLength embind ArrayBuffer.byteLength
Map GAP GAP - No direct equivalent Asm.js / Wasm modules are unable to map regions of an ArrayBuffer other than their single linear memory heap. Future multiple memories or memory mapping might improve this.
Unmap GAP GAP - No direct equivalent

PPB_VarDictionary

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind {}
Get embind <Object>[i]
Set embind <Object>[i] = x
Delete embind delete <Object>[i]
HasKey embind x in <Object>
GetKeys embind for (k in <Object>) {} No literal equivalent, but it can be built.

PPB_VideoDecoder

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - Would be handled with the proposed WebCodecs API using VideoDecoder() https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
Initialize GAP GAP - Would be handled with the proposed WebCodecs API using VideoDecoder() initialization parameters (VideoDecoderInitParameters) https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
Decode GAP GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoDecoder) https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
GetPicture GAP GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoDecoder).pipeTo(VideoTrackWriter().writable) https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
RecyclePicture GAP GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the pictures and keep the decoding process going. https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
Flush GAP GAP - Would be handled with the proposed WebCodecs API. The API will be called Flush(), however there is still discussion on how it will be sequenced in relation to decode calls. https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
Reset GAP GAP - Would be handled with the proposed WebCodecs API by destroying the VideoDecoder instance and creating a new one. This won't be as efficient as a dedicated reset method, but the semantics for a Reset() API is still being discussed. https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming

PPB_VideoEncoder

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - Would be handled with the proposed WebCodecs API using VideoEncoder()
GetSupportedProfiles GAP GAP (partial) - navigator.mediaCapabilities.encodingInfo() The supported profiles have to be checked one by one.
Initialize GAP GAP - Would be handled with the proposed WebCodecs API using VideoEncoder() initialization parameters
GetFramesRequired GAP GAP - No equivalent It is unlikely that the frame pool used internally by the Web Codecs API is exposed.
GetFrameCodedSize GAP GAP - No equivalent It is unlikely that the frame pool used internally by the Web Codecs API is exposed.
GetVideoFrame GAP GAP - Would be handled with the proposed WebCodecs API by using ReadableStream.pipeThrough(VideoEncoder). This would directly encode the data in the Readable stream instead of grabbing a single frame to fill with data before encoding.
Encode GAP GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoEncoder)
GetBitstreamBuffer GAP GAP - Would be handled with the proposed WebCodecs API. The current design will automatically go through the encoded bitstream buffer that is piped through. The WebCodecs API currently assumes that bitstream buffer can be copied rather than pooled, so it will not need to be recycled.
RecycleBitstreamBuffer GAP GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the buffer to keep the encoding process going. This is unlikely to change in the future as performance implications are smaller.
RequestEncodingParametersChange GAP GAP - Would be handled by the proposed Web Codecs API. Certain parameters will have the capability of being changed on the fly, while others will require the encoder to be torn down.
Close GAP GAP - Would be handled with the proposed WebCodecs API by using VideoEncoder.Close()

PPB_VideoFrame

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetTimestamp GAP GAP - Would be handled with the proposed WebCodecs API.
SetTimestamp GAP GAP - Would be handled with the proposed WebCodecs API.
GetFormat GAP GAP - Would be handled with the proposed WebCodecs API.
GetSize GAP GAP - Would be handled with the proposed WebCodecs API.
GetDataBuffer GAP GAP - Would be handled with the proposed WebCodecs API.
GetDataBufferSize GAP GAP - Would be handled with the proposed WebCodecs API.

PPB_View

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetRect embind Element.getBoundingClientRect
IsFullscreen embind Document.fullScreenEnabled Pertains to document instead of just single element.
IsVisible embind IntersectionObserver
IsPageVisible embind document.visibilityState
GetClipRect embind IntersectionObserver
GetDeviceScale embind window.devicePixelRatio
GetCSSScale embind <Element>.getBoundingClientRect().width / <Element>.offsetWidth
GetScrollOffset embind <Element>.scrollTop / <Element>.scrollLeft

PPB_WebSocket

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP WebSocket.WebSocket
Connect GAP WebSocket.WebSocket(url, ...) WebSocket 'open' Event
Close GAP WebSocket.close
ReceiveMessage GAP WebSocket 'message' Event WebSocket 'error' Event WebSocket 'close' Event
SendMessage GAP WebSocket.send
GetBufferedAmount GAP WebSocket.bufferedAmount
GetCloseCode GAP CloseEvent.code
GetCloseReason GAP CloseEvent.reason
GetCloseWasClean GAP CloseEvent.wasClean
GetExtensions GAP WebSocket.extensions
GetProtocol GAP WebSocket.protocol
GetReadyState GAP WebSocket.readyState
GetURL GAP WebSocket.url

PPP_Graphics3D

PPAPI Method Assumes Threads Emscripten Web API Limitations
Graphics3DContextLost SDL Canvas 'webglcontextlost' Event

PPP_InputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleInputEvent SDL Element.addEventListener

PPP_Instance

PPAPI Method Assumes Threads Emscripten Web API Limitations
DidCreate N/A <Element>[key] General DOM access lets you fish out tag attributes
DidDestroy N/A N/A Not triggered for NaCl
DidChangeView N/A Element 'resize' Event
DidChangeFocus N/A Element 'focus', 'focusin', 'focusout' Events
HandleDocumentLoad N/A GAP - No way to register as a mime type handler NaCl Modules via apps + a manifest entry can be set up to handle particular mime types.

PPP_MessageHandler

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleMessage embind MessagePort 'message' Event Window 'message' Event
HandleBlockingMessage N/A GAP - No direct equivalent Similar synchronization can be done off main thread with Atomics.wait. This was added to support emulation of synchronous plugin APIs.

PPP_Messaging

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleMessage embind MessagePort 'message' Event Window 'message' Event

PPP_MouseLock

PPAPI Method Assumes Threads Emscripten Web API Limitations
MouseLockLost SDL Element 'pointerlockchange', 'pointerlockerror' Events

IRT

PPB_Audio

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x SDL (partial) GAP (partial) - AudioWorkletNode ROUGHLY equivalent The AudioWorkletSpec is done, but AudioDeviceClient may be a better fit for this API. The AudioDeviceClient is still being specified by the community. The worklet may not be the rough equivalent for this API.
GetCurrentConfig SDL AudioContext.* (gets back settings passed in)
StartPlayback SDL AudioBufferSourceNode.start
StopPlayback SDL AudioBufferSourceNode.stop

PPB_AudioBuffer

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetTimestamp SDL AudioBufferSourceNode.start (parameter) Passed in each time instead of attached to the buffer.
SetTimestamp SDL AudioBufferSourceNode.start (parameter)
GetSampleRate SDL AudioBuffer.sampleRate
GetSampleSize GAP GAP - WebAudio only uses 32-bit float, PPAPI does 16-bit int. PPAPI theoretically supports multiple sampling sizes. In practice, it only supports 16-bit samples. Unfortunately, developers have requested 16-bit sample sizes to save on memory use. The next version of the Web Audio spec will implement support for 16-bit samples. An optimization for AudioBuffer could be implemented similar to Firefox by using 16-bit buffer for audio that comes from decodeAudioData
GetNumberOfChannels SDL AudioBuffer.numberOfChannels
GetDataBuffer SDL AudioBuffer.getChannelData
GetBufferSize SDL AudioBuffer.length

PPB_AudioConfig

PPAPI Method Assumes Threads Emscripten Web API Limitations
CreateStereo16Bit GAP GAP - Only 32-bit float samples supported The next version of the Web Audio spec will implement support for 16-bit samples.
GetSampleRate SDL AudioContext.sampleRate
GetSampleFrameCount SDL AudioBuffer.length
RecommendSampleRate SDL AudioContext.sampleRate (from default construct) An AudioContext will have the preferred sampling rate that matchs the actual sample rate of the hardware audio device by default.
RecommendSampleFrameCount GAP GAP - Would be handled with the planned AudioDeviceClient There is an open issue to allow a user-specified size, but that is still being defined. This is probably best handled with AudioDeviceClient which can tell you what the appropriate size would be for the given hardware.

PPB_Console

PPAPI Method Assumes Threads Emscripten Web API Limitations
Log utime console.log/warn/error/...
LogWithSource GAP GAP The Console API is regarded as a sufficiently complete replacement, unless there are specific use cases raised by developers for the functionality provided by LogWithSource. DevTools Source Maps can be used to debug transpiled JavaScript in their original source language.

PPB_Core

PPAPI Method Assumes Threads Emscripten Web API Limitations
getTime utime new Date().getTime()
getTimeTicks utime new Date().getTime()
IsMainThread GAP window.document !== undefined
CallOnMainThread GAP Worker.postMessage + Atomics.wait Equivalent synchronization can be built.

PPB_FileIO

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) window.chooseFileSystemEntries() Create and open are used differently, but the pieces are of equal power.
Open FS (partial) window.chooseFileSystemEntries()
Query FS (partial) Blob.size, FileSystemHandle.getFile(), FileSystemHandle.getDirectory(), File.lastModified GAP (partial) - Blob.type can also be used to check the MIME type. The file system type, creation time, and last access time can not be determined with the Native File System API.
Touch FS (partial) FileSystemDirectoryHandle.getFile("name", {create: true})
Read FS (partial) Blob.slice().arrayBuffer()
Write FS (partial) FileSystemWriter.write()
SetLength FS (partial) FileSystemWriter.truncate()
Flush GAP (partial) GAP (partial) - Files are flushed when FileSystemWrite.close() is called This is intended by design because the Native File System API files are exposed to the OS, therefore a Safe Browsing check needs to be performed before data is shown to the OS.
Close FS (partial) FileSystemWriter.close() Does not cancel pending operations, but flushes any data written so far to disk.
ReadToArray GAP Blob.slice().arrayBuffer() or Blob.arrayBuffer() Allows multiple subrange reads in parallel.

PPB_FileRef

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) FileSystemDirectoryHandle.getFile("name", {create: true})
GetFileSystemType FS (partial) FileSystem.type
GetName FS (partial) File.name
GetPath FS (partial) GAP (partial) - With the Native File System API, the relative path of a file can be determined from reference to a directory that contains the file using FileSystemHandle.resolve(FileSystemHandle) The absolute path of a file cannot be determined, and the user has to grant permission to access the directory containing the file.
GetParent FS (partial) GAP (partial) - With the Native File System API, the relative path of a file can be determined from reference to a directory that contains the file using FileSystemHandle.resolve(FileSystemHandle) The user has to grant permission to access the directory containing the file.
MakeDirectory FS (partial) FileSystemHandle.getDirectory(..., {createIfNotExists: true})
Touch FS (partial) FileSystemDirectoryHandle.getFile("name", {create: true}) Modify time can be bumped by writing.
Delete FS (partial) FileSystemDirectoryHandle.removeEntry() Unlike the PPAPI, directories do not have to be empty.
Rename FS (partial) GAP (partial) - With the Native File System API, the file can be written with the new name using a combination of FileSystemFileHandle.getFile() for the new name and FileSystemFileHandle.createWriter().write() with the contents of the old file. Then FileSystemDirectoryHandle.removeEntry() to delete the old file. There is not a direct API that will do this in one step in the Native File System API.
Query GAP (partial) Blob.size, FileSystemHandle.getFile(), FileSystemHandle.getDirectory(), File.lastModified GAP (partial) - Blob.type can also be used to check the MIME type. The file system type, creation time, and last access time can not be determined with the Native File System API.
ReadDirectoryEntries FS (partial) FileSystemDirectoryHandle.getEntries()

PPB_FileSystem

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create FS (partial) window.requestFileSystem JS API does both in one step
Open GAP window.requestFileSystem JS API does both in one step
GetType GAP FileSystem.type

PPB_Fullscreen

PPAPI Method Assumes Threads Emscripten Web API Limitations
IsFullScreen html5.h Document.fullscreenEnabled
SetFullscreen html5.h Document.requestFullscreen
GetScreenSize html5.h Document.exitFullscreen

PPB_Gamepad

PPAPI Method Assumes Threads Emscripten Web API Limitations
Sample SDL Gamepad.* The Gamepad object exposes a timestamp relative to navigationStart. It is updated when data is received from the hardware https://www.w3.org/TR/gamepad/#gamepad-interface

PPB_Graphics2D

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL Canvas.getContext('2d')
Describe SDL Canvas.clientWidth + Canvas.clientHeight
PaintImageData SDL CanvasRenderingContext2D.putImageData
Scroll GAP CanvasRenderingContext2D.scrollIntoView, CanvasRenderingContext2D.drawImage GAP (partial) - Can be implemented by drawing the canvas onto itself, with an offset, using drawImage, and then filling in the rest.
ReplaceContents SDL CanvasRenderingContext2D.drawImage
Flush GAP No direct equivalent GAP (partial) - There is always an implicit flush at the end of draw code; this is unlikely to change. However, the combination of OffscreenCanvas and ImageBitmapRenderingContext provide similar functionality.
SetScale SDL CanvasRenderingContext2D.scale
GetScale SDL CanvasRenderingContext2D.currentTransform
SetLayerTransform SDL CanvasRenderingContext2D.setTransform CanvasRenderingContext2D.scale CanvasRenderingContext2D.translate

PPB_Graphics3D

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetAttribMaxValue OpenGL ES 3.0 WebGL 2.0 GAP (partial) - WebGL 2.0 and Emscripten's exposure of OpenGL ES 3.0 support user-defined multisampled framebuffers, in which all of the parameters configurable via PPAPI can be set.
Create SDL Canvas.getContext
GetAttribs SDL WebGLRenderingContext.getContextAttributes
SetAttribs SDL Canvas.getContext(.., OPTIONS)
GetError SDL WebGLRenderingContext.getError
ResizeBuffers SDL Canvas.width = w; Canvas.height = h;
SwapBuffers GAP No direct equivalent GAP (partial) - There is always an implicit flush at the end of draw code; this is unlikely to change. However, the combination of OffscreenCanvas and ImageBitmapRenderingContext provide similar functionality.

PPB_ImageData

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetNativeImageDataFormat SDL ImageData mandates RGBA order
IsImageDataFormatSupported SDL ImageData mandates RGBA order
Create SDL CanvasRenderingContext2d.createImageData
Describe SDL ImageData never has a stride
Map SDL ImageData.data
Unmap SDL ImageData.data

PPB_InputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
RequestInputEvents SDL No direct equivalent The lack of this feature is probably less relevant as JS / Wasm runs on the main thread and can more cheaply filter events without incurring a cross process round-trip.
RequestFilteringInputEvents SDL mouse* key* wheel* touch* composition* Events
SDL Element.addEventListener
ClearInputEventRequest SDL Element.removeEventListener
GetType SDL Event class descendants
GetTimeStamp SDL Event.timeStamp
GetModifiers SDL *Event.altKey/shiftKey/metaKey/ctrlKey

PPB_MouseInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL MouseEvent
GetButton SDL MouseEvent.button
GetPosition SDL MouseEvent.client*/page*/offset*
GetClickCount SDL dblclick' vs 'mousedown' Events
GetMovement SDL MouseEvent.movement*

PPB_WheelInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL WheelEvent
GetDelta SDL WheelEvent.delta*
GetTicks GAP GAP - deltaMode kind of contains this info, but incompletely. There is discussion on implementing a WheelEvent.deltaMode API: https://github.com/w3c/uievents/issues/181#issuecomment-537811017
GetScrollByPage GAP GAP - deltaMode kind of contains this info, but incompletely. There is discussion on implementing a WheelEvent.deltaMode API: https://github.com/w3c/uievents/issues/181#issuecomment-537811017

PPB_KeyboardInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL KeyboardEvent
GetKeyCode SDL KeyboardEvent.keyCode
GetCharacterText SDL KeyboardEvent.key
GetCode SDL KeyboardEvent.code

PPB_TouchInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create SDL TouchEvent
AddTouchPoint SDL TouchEvent.touches.push
GetTouchCount SDL TouchEvent.touches.length
GetTouchByIndex SDL TouchEvent.touches[i]
GetTouchById SDL Touch.indentifer (to figure this out yourself)

PPB_IMEInputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP CompositionEvent
GetText GAP CompositionEvent.data
GetSegmentNumber GAP GAP - No direct equivalent This data can potentially be retrieved from CompositionEvent.data.
GetSegmentOffset GAP GAP - No direct equivalent
GetTargetSegment GAP GAP - No direct equivalent
GetSelection GAP GAP - No direct equivalent

PPB_Instance

PPAPI Method Assumes Threads Emscripten Web API Limitations
BindGraphics SDL Canvas.getContext (moot as binding is automatic).
IsFullFrame GAP GAP - No equivalent to mime type handlers. NaCl apps can be registered to handle a particular mime type and own the whole document.
DidCreate N/A <Element>[key] General DOM access lets you fish out tag attributes
DidDestroy N/A N/A Not triggered for NaCl
DidChangeView N/A Element 'resize' Event
DidChangeFocus N/A Element 'focus', 'focusin', 'focusout' Events
HandleDocumentLoad N/A GAP - No way to register as a mime type handler NaCl modules via apps + a manifest entry can be set up to handle particular mime types.

PPB_MediaStreamAudioTrack

PPAPI Method Assumes Threads Emscripten Web API Limitations
Configure GAP getUserMedia() The constraints from getUserMedia() can provide the configuration values to use in MediaStreamTrack.
GetAttrib GAP MediaStreamTrack.getSettings()
GetId GAP MediaStreamTrack.id
HasEnded GAP MediaStreamTrack.readyState
GetBuffer GAP GAP - No equivalent
RecycleBuffer GAP GAP - No equivalent
Close GAP MediaStreamTrack.stop()

PPB_MediaStreamVideoTrack

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP Canvas Capture Canvas Capture provides the ability to introduce video frames programatically.
Configure GAP applyConstraints(), getUserMedia() GAP (partial) - The extent of configurations available in the Web API may differ from the PPAPI.
GetAttrib GAP MediaStreamSettings.width
GAP MediaStreamSettings.height
GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_BUFFERED_FRAMES MediaStream cannot be preloaded, so it will never buffer: https://www.w3.org/TR/mediacapture-streams/#mediastreams-in-media-elements
GAP GAP - no equivalent to PP_MEDIASTREAMVIDEOTRACK_ATTRIB_FORMAT
GetId GAP MediaStreamTrack.id
HasEnded GAP MediaStreamTrack.readyState
GetFrame GAP GAP - No equivalent
RecycleFrame GAP GAP - No equivalent
Close GAP MediaStreamTrack.stop()
GetEmptyFrame GAP GAP - No equivalent
PutFrame GAP GAP - No equivalent

PPB_MessageLoop

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create N/A Mostly moot, workers get an implicit event loop.
GetForMainThread N/A Mostly moot, workers get an implicit event loop.
GetCurrent N/A Mostly moot, workers get an implicit event loop.
AttachToCurrentThread N/A Mostly moot, workers get an implicit event loop.
Run N/A Mostly moot, workers get an implicit event loop.
PostWork N/A Mostly moot, workers get an implicit event loop.
PostQuit N/A Mostly moot, workers get an implicit event loop.

PPB_Messaging

PPAPI Method Assumes Threads Emscripten Web API Limitations
PostMessage N/A Window.postMessage
RegisterMessageHandler N/A Window.addEventListener
UnregisterMessageHandler N/A Window.removeEventListener

PPB_MouseCursor

PPAPI Method Assumes Threads Emscripten Web API Limitations
SetCursor SDL Element.style.cursor Same set of stock cursors are supported. Custom cursors can be done with url(..). Dynamic custom cursors can be done with data URIs. CSS3 supports specifying the hotspot.

PPB_MouseLock

PPAPI Method Assumes Threads Emscripten Web API Limitations
LockMouse SDL Element.requestPointerLock
UnlockMouse SDL Element.exitPointerLock

PPB_OpenGLES2

PPAPI Method Assumes Threads Emscripten Web API Limitations
Several Methods OpenGLES Close to WebGL 1.0 in functionality.
x OffscreenCanvas

PPB_TextInputController

PPAPI Method Assumes Threads Emscripten Web API Limitations
SetTextInputType GAP GAP - Potentially filled by Input Method Editor API Some developers would like to either be able to hint in this fashion, or preferrably the ability to intercept and display IME events / output inline inside a canvas.
UpdateCaretPosition GAP GAP - Potentially filled by Input Method Editor API https://www.w3.org/TR/ime-api/
CancelCompositionText GAP GAP - Potentially filled by Input Method Editor API https://www.w3.org/TR/ime-api/
UpdateSurroundingText GAP GAP - Potentially filled by Input Method Editor API https://www.w3.org/TR/ime-api/

PPB_URLLoader

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind new XMLHttpRequest();
Open embind XMLHttpRequest.open
FollowRedirect embind Request.redirect
GAP GAP - No XMLHTTPRequest equivalent
GetUploadProgress embind XMLHttpRequest 'progress' Event
GAP FetchObserver Not specced or implemented yet; https://github.com/whatwg/fetch/issues/607
GetDownloadProgress embind XMLHttpRequest 'progress' Event
GAP FetchObserver Not specced or implemented yet; https://github.com/whatwg/fetch/issues/607
GetResponseInfo embind XMLHttpRequest.getAllResponseHeaders
embind Fetch Response.*
ReadResponseBody embind XMLHttpRequest.response
embind Body.* (Response is a Body)
FinishStreamingToFile embind GAP - No direct equivalent XMLHttpRequest and Fetch both assume streaming to memory, rather than directly to a storage.
Close embind XMLHttpRequest.abort
GAP Fetch API: AbortSignal and AbortController

PPB_URLRequestInfo

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind XMLHttpRequest
embind Fetch Request
SetProperty GAP GAP - No direct equivalent for XMLHttpRequest XMLHttpRequest doesn't provide direct ways to per-request limit following redirects, stream to a file, set referrer or credentials policy.
embind Request.*
AppendDataToBody embind XMLHttpRequest.send GAP - Both must have the whole body, rather than a chunk.
embind fetch(.., options:body)
AppendFileToBody GAP fetch() upload streaming https://www.chromestatus.com/features/5274139738767360
N/A <form> You can also read with FileReader and upload, but that's more like AppendDataToBody

PPB_URLResponseInfo

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetProperty embind XMLHttpRequest.getAllResponseHeaders + others
embind Fetch Response.*
GetBodyAsFileRef embind Fetch Response (Body) .blob() Assumes storage layer optimizes transfer.

PPB_Var

PPAPI Method Assumes Threads Emscripten Web API Limitations
VarFromUtf8 embind TextDecoder.decode
VarToUtf8 embind TextEncoder.encode
VarFromResource N/A N/A
VarToResource N/A N/A

PPB_VarArray

PPAPI Method Assumes Threads Emscripten Web API Limitations
Get embind Array[i]
Set embind Array[i] = x
GetLength embind Array.length
SetLength embind Array.length = n

PPB_VarArrayBuffer

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind new ArrayBuffer(n)
ByteLength embind ArrayBuffer.byteLength
Map GAP GAP - No direct equivalent Asm.js / Wasm modules are unable to map regions of an ArrayBuffer other than their single linear memory heap. Future multiple memories or memory mapping might improve this.
Unmap GAP GAP - No direct equivalent

PPB_VarDictionary

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create embind {}
Get embind <Object>[i]
Set embind <Object>[i] = x
Delete embind delete <Object>[i]
HasKey embind x in <Object>
GetKeys embind for (k in <Object>) {} No literal equivalent, but it can be built.

PPB_VideoDecoder

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - Would be handled with the proposed WebCodecs API using VideoDecoder() https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
Initialize GAP GAP - Would be handled with the proposed WebCodecs API using VideoDecoder() initialization parameters (VideoDecoderInitParameters) https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
Decode GAP GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoDecoder) https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
GetPicture GAP GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoDecoder).pipeTo(VideoTrackWriter().writable) https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
RecyclePicture GAP GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the pictures and keep the decoding process going. https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
Flush GAP GAP - Would be handled with the proposed WebCodecs API. The API will be called Flush(), however there is still discussion on how it will be sequenced in relation to decode calls. https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming
Reset GAP GAP - Would be handled with the proposed WebCodecs API by destroying the VideoDecoder instance and creating a new one. This won't be as efficient as a dedicated reset method, but the semantics for a Reset() API is still being discussed. https://github.com/WICG/web-codecs/blob/master/explainer.md#example-of-decode-for-low-latency-live-streaming-or-cloud-gaming

PPB_VideoEncoder

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP GAP - Would be handled with the proposed WebCodecs API using VideoEncoder()
GetSupportedProfiles GAP GAP (partial) - navigator.mediaCapabilities.encodingInfo() The supported profiles have to be checked one by one.
Initialize GAP GAP - Would be handled with the proposed WebCodecs API using VideoEncoder() initialization parameters
GetFramesRequired GAP GAP - No equivalent It is unlikely that the frame pool used internally by the Web Codecs API is exposed.
GetFrameCodedSize GAP GAP - No equivalent It is unlikely that the frame pool used internally by the Web Codecs API is exposed.
GetVideoFrame GAP GAP - Would be handled with the proposed WebCodecs API by using ReadableStream.pipeThrough(VideoEncoder). This would directly encode the data in the Readable stream instead of grabbing a single frame to fill with data before encoding.
Encode GAP GAP - Would be handled with the proposed WebCodecs API using ReadableStream.pipeThrough(VideoEncoder)
GetBitstreamBuffer GAP GAP - Would be handled with the proposed WebCodecs API. The current design will automatically go through the encoded bitstream buffer that is piped through. The WebCodecs API currently assumes that bitstream buffer can be copied rather than pooled, so it will not need to be recycled.
RecycleBitstreamBuffer GAP GAP - Would be handled with the proposed WebCodecs API. The current design will automatically recycle the buffer to keep the encoding process going. This is unlikely to change in the future as performance implications are smaller.
RequestEncodingParametersChange GAP GAP - Would be handled by the proposed Web Codecs API. Certain parameters will have the capability of being changed on the fly, while others will require the encoder to be torn down.
Close GAP GAP - Would be handled with the proposed WebCodecs API by using VideoEncoder.Close()

PPB_VideoFrame

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetTimestamp GAP GAP - Would be handled with the proposed WebCodecs API.
SetTimestamp GAP GAP - Would be handled with the proposed WebCodecs API.
GetFormat GAP GAP - Would be handled with the proposed WebCodecs API.
GetSize GAP GAP - Would be handled with the proposed WebCodecs API.
GetDataBuffer GAP GAP - Would be handled with the proposed WebCodecs API.
GetDataBufferSize GAP GAP - Would be handled with the proposed WebCodecs API.

PPB_View

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetRect embind Element.getBoundingClientRect
IsFullscreen embind Document.fullScreenEnabled Pertains to document instead of just single element.
IsVisible embind IntersectionObserver
IsPageVisible embind document.visibilityState
GetClipRect embind IntersectionObserver
GetDeviceScale embind window.devicePixelRatio
GetCSSScale embind <Element>.getBoundingClientRect().width / <Element>.offsetWidth
GetScrollOffset embind <Element>.scrollTop / <Element>.scrollLeft

PPB_WebSocket

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create GAP WebSocket.WebSocket
Connect GAP WebSocket.WebSocket(url, ...) WebSocket 'open' Event
Close GAP WebSocket.close
ReceiveMessage GAP WebSocket 'message' Event WebSocket 'error' Event WebSocket 'close' Event
SendMessage GAP WebSocket.send
GetBufferedAmount GAP WebSocket.bufferedAmount
GetCloseCode GAP CloseEvent.code
GetCloseReason GAP CloseEvent.reason
GetCloseWasClean GAP CloseEvent.wasClean
GetExtensions GAP WebSocket.extensions
GetProtocol GAP WebSocket.protocol
GetReadyState GAP WebSocket.readyState
GetURL GAP WebSocket.url

PPP_Graphics3D

PPAPI Method Assumes Threads Emscripten Web API Limitations
Graphics3DContextLost SDL Canvas 'webglcontextlost' Event

PPP_InputEvent

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleInputEvent SDL Element.addEventListener

PPP_Instance

PPAPI Method Assumes Threads Emscripten Web API Limitations
DidCreate N/A <Element>[key] General DOM access lets you fish out tag attributes
DidDestroy N/A N/A Not triggered for NaCl
DidChangeView N/A Element 'resize' Event
DidChangeFocus N/A Element 'focus', 'focusin', 'focusout' Events
HandleDocumentLoad N/A GAP - No way to register as a mime type handler NaCl Modules via apps + a manifest entry can be set up to handle particular mime types.

PPP_MessageHandler

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleMessage embind MessagePort 'message' Event Window 'message' Event
HandleBlockingMessage N/A GAP - No direct equivalent Similar synchronization can be done off main thread with Atomics.wait. This was added to support emulation of synchronous plugin APIs.

PPP_Messaging

PPAPI Method Assumes Threads Emscripten Web API Limitations
HandleMessage embind MessagePort 'message' Event Window 'message' Event

PPP_MouseLock

PPAPI Method Assumes Threads Emscripten Web API Limitations
MouseLockLost SDL Element 'pointerlockchange', 'pointerlockerror' Events

PPAPI (Apps)

PPB_HostResolver

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x GAP GAP (partial) - No direct equivalent
Resolve x GAP GAP (partial) - No direct equivalent
GetCanonicalName x GAP GAP (partial) - No direct equivalent
GetNetAddressCount x GAP GAP (partial) - No direct equivalent
GetNetAddress x GAP GAP (partial) - No direct equivalent

PPB_NetAddress

PPAPI Method Assumes Threads Emscripten Web API Limitations
CreateFromIPv4Address x GAP GAP (partial) - No direct equivalent
CreateFromIPv6Address x GAP GAP (partial) - No direct equivalent
GetFamily x GAP GAP (partial) - No direct equivalent
DescribeAsString x GAP GAP (partial) - No direct equivalent
DescribeAsIPv4Address x GAP GAP (partial) - No direct equivalent
DescribeAsIPv6Address x GAP GAP (partial) - No direct equivalent

PPB_NetworkList

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetCount x GAP GAP - No direct equivalent
GetName x GAP GAP - No direct equivalent
GetType x GAP GAP - No direct equivalent
GetState x GAP GAP - No direct equivalent
GetIpAddress x GAP GAP - No direct equivalent
GetDisplayName x GAP GAP - No direct equivalent
GetMTU x GAP GAP - No direct equivalent

PPB_NetworkMonitor

PPAPI Method Assumes Threads Emscripten Web API Limitations
Create x GAP GAP - No direct equivalent
UpdateNetworkList x GAP GAP - No direct equivalent

PPB_NetworkProxy

PPAPI Method Assumes Threads Emscripten Web API Limitations
GetProxyForURL x GAP GAP - No direct equivalent

PPB_TCPSocket and PPB_UDPSocket

There is not a direct 1:1 mapping for migration. Instead, we have outlined some user scenarios below and what the recommended migration path is.
Use Case Recommendations
Screen sharing getDisplayMedia and WebRTC ( demo)
Loading from a local server to minimize bandwidth usage XHR, Fetch, Streams, Service Worker, Cache APIs
Loading from a local instance of a web app / Connecting to a local instance of a web app WebRTC
Chat WebSocket*
Realtime audio/video communication WebRTC
Collaboration WebSocket*
Realtime multiplayer games WebTransport** unless P2P in which case WebRTC (or WebTransport over RTCIceTransport)
Realtime interactive streaming WebTransport**
Communicating with legacy server Proxy server or middleware to do protocol conversion. Feedback to bit.ly/network-api-gaps
*: Or WebTransport in the future
**: See chromestatus for availability